package br.ufrgs.meetapp.lists;

import java.util.ArrayList;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Filter;
import android.widget.TextView;
import br.ufrgs.meetapp.activities.R;
import br.ufrgs.meetapp.activities.TrackOthersTabActivity;
import br.ufrgs.meetapp.models.Buddy;

import com.google.android.maps.GeoPoint;

public class BuddyListArrayAdapter extends ArrayAdapter<Buddy> {

	private LayoutInflater layoutInflater;
	private int layoutResource;
	private ArrayList<Buddy> buddyList;
	private ArrayList<Buddy> originalBuddyList = new ArrayList<Buddy>();
	private BuddyFilter buddyFilter;
	private final Object mLock = new Object();
	
	public BuddyListArrayAdapter(Context context, int textViewResourceId, ArrayList<Buddy> objects) {
		super(context, textViewResourceId, objects);
		this.layoutInflater = LayoutInflater.from(context);
		this.layoutResource = textViewResourceId;
		this.buddyList = objects;
		cloneItems(objects);
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		
		final ViewHolder holder;
		holder = new ViewHolder();		
		convertView = layoutInflater.inflate(layoutResource, null);
		holder.cellTitle = (TextView) convertView.findViewById(R.id.cell_buddy_list_name);
		holder.cellDate = (TextView) convertView.findViewById(R.id.cell_buddy_list_date);
		holder.cellDistance = (TextView) convertView.findViewById(R.id.cell_buddy_list_distance);
		holder.cellDetailButton = (Button) convertView.findViewById(R.id.cell_buddy_list_detail_button);
		
		final Buddy buddy = buddyList.get(position);
		
		holder.cellTitle.setText(buddy.getBuddyName());
		
		try{
			holder.cellDate.setText(buddy.getPositionDate().toLocaleString()); 
		}
		catch (Exception ex)
		{
			Log.i("MFT - BuddyListArrayAdapter ", "Error converting date: "+ex.getMessage());
			holder.cellDate.setText(""); 
		}
		
		
		GeoPoint buddyGeoPoint = new GeoPoint(buddy.getLatitude(), buddy.getLongitude());
		holder.cellDistance.setText(TrackOthersTabActivity.getDistanceBetweenTwoGeoPoints(TrackOthersTabActivity.myLocation, buddyGeoPoint));
		
		return convertView;
	}
	
	/**
	 * 
	 * @return the orignal BuddyList
	 */
	public ArrayList<Buddy> getOriginalBuddyList(){
		if(originalBuddyList != null){
			return originalBuddyList;
		} else {
			return new ArrayList<Buddy>();
		}	 
	}
	
	/**
	 * View Holder for the cell.
	 * Contains all the text views that will be setted.
	 * 
	 */
	public static class ViewHolder{
		TextView cellTitle;
		TextView cellDate;
		TextView cellDistance;
		Button cellDetailButton;
	}

	/**
     * Implementing the Filterable interface.
     */
    public Filter getFilter() {
        if (buddyFilter == null) {
        	buddyFilter = new BuddyFilter();
        }
        return buddyFilter;
    } 
    
    /**
     * Clone the buddyList to retain the original list
     * @param items
     */
    public void cloneItems(ArrayList<Buddy> items) {
        for (Buddy buddy : items) {
            originalBuddyList.add(buddy);
        }
    }

    @Override
    public int getCount() {
        synchronized(mLock) {
            return buddyList!=null ? buddyList.size() : 0;  
        }
    }

    @Override
    public Buddy getItem(int item) {
        Buddy buddy = null;
        synchronized(mLock) {
                buddy = buddyList!=null ? buddyList.get(item) : null;

        }
        return buddy;
    }
	
    /**
     * Called to refresh the list
     * @param new BuddyList
     * @param string filter
     */
    public void refreshList(ArrayList<Buddy> objects, String filterText){
    	buddyList = objects;
    	originalBuddyList.clear();
		cloneItems(objects);
		getFilter().filter(filterText);		
		notifyDataSetChanged();
    }
    
	
	/**
     * Custom Filter implementation for the items adapter.
     *
     */
    private class BuddyFilter extends Filter {
        protected FilterResults performFiltering(CharSequence prefix) {
            // Initiate our results object
            FilterResults results = new FilterResults();

            // No prefix is sent to filter by so we're going to send back the original array
            if (prefix == null || prefix.length() == 0) {
                synchronized (mLock) {
                    results.values = originalBuddyList;
                    results.count = originalBuddyList.size();
                }
            } else {
                synchronized(mLock) {
                        // Compare lower case strings
                    String prefixString = prefix.toString().toLowerCase();
                    final ArrayList<Buddy> filteredItems = new ArrayList<Buddy>();
                    // Local to here so we're not changing actual array
                    final ArrayList<Buddy> localItems = new ArrayList<Buddy>();
                    localItems.addAll(originalBuddyList);
                    final int count = localItems.size();

                    for (int i = 0; i < count; i++) {
                        final Buddy buddy = localItems.get(i);
                        final String buddyName = buddy.getBuddyName().toString().toLowerCase();

                        // First match against the whole, non-splitted value
                        if (buddyName.startsWith(prefixString)) {
                            filteredItems.add(buddy);
                        } else { 
                            final String[] words = buddyName.split(" ");
                            final int wordCount = words.length;

                            for (int k = 0; k < wordCount; k++) {
                                if (words[k].startsWith(prefixString)) {
                                	filteredItems.add(buddy);
                                    break;
                                }
                            }
                        } 
                    }

                    // Set and return
                    results.values = filteredItems;
                    results.count = filteredItems.size();
                }//end synchronized
            }

            return results;
        }

        @Override
        protected void publishResults(CharSequence prefix, FilterResults results) {
            synchronized(mLock) {
                @SuppressWarnings("unchecked")
				final ArrayList<Buddy> localItems = (ArrayList<Buddy>) results.values;
                
                //Remove the elements and insert the filtered elements
                buddyList.clear();
                for (Buddy buddy : localItems){
                	buddyList.add(buddy);
                }
      
                notifyDataSetChanged();
            }
        }
    }
	
}
